﻿using System;
using System.Collections.Generic;
using System.Text;

namespace PickGold.Security
{
	public class CDES
	{
		private static Encoding _DefaultEncoding;

		/// <summary>
		/// 设置或获取默认字符集
		/// </summary>
		public static Encoding DefaultEncoding
		{
			set
			{
				CDES._DefaultEncoding = value;
			}
			get
			{
				if (CDES._DefaultEncoding == null)
					return Encoding.UTF8;

				return CDES._DefaultEncoding;
			}
		}

		public static byte[] Encrypt(Guid key, string input)
		{
			if (input == null)
				input = string.Empty;
			return CDES.Encrypt(key, CDES.DefaultEncoding.GetBytes(input));
		}

		public static byte[] Encrypt(Guid key, byte[] input)
		{
			return CDES.Encrypt(key.ToByteArray(), input);
		}

		public static byte[] Encrypt(string key, string input)
		{
			if (input == null)
				input = string.Empty;
			return CDES.Encrypt(key, CDES.DefaultEncoding.GetBytes(input));
		}

		public static byte[] Encrypt(string key, byte[] input)
		{
			if (key == null)
				key = string.Empty;
			var bs = CDES.DefaultEncoding.GetBytes(key);
			bs = CMD5.MD5.ComputeHash(bs);
			return CDES.Encrypt(bs, input);
		}

		public static byte[] Encrypt(byte[] key, string input)
		{
			if (input == null)
				input = string.Empty;
			return CDES.Encrypt(key, CDES.DefaultEncoding.GetBytes(input));
		}

		public static byte[] Encrypt(byte[] key, byte[] input)
		{
			if (key == null || key.Length == 0)
				return CDES.Encrypt(string.Empty, input);

			var des = System.Security.Cryptography.DES.Create();
			if (key.Length != 8)
				key = CMD5.MD5.ComputeHash(key);
			des.Key = new byte[] { key[0], key[2], key[4], key[6], key[8], key[10], key[12], key[14] };
			des.IV = new byte[] { key[1], key[3], key[5], key[7], key[9], key[11], key[13], key[15] };
			var ms = new System.IO.MemoryStream();
			ms.WriteByte(0);
			var cs = new System.Security.Cryptography.CryptoStream(ms, des.CreateEncryptor(), System.Security.Cryptography.CryptoStreamMode.Write);
			cs.Write(input, 0, input.Length);
			cs.Flush();
			cs.FlushFinalBlock();
			cs.Close();
			input = ms.ToArray();
			ms.Close();
			des.Clear();

			return input;
		}

		public static string EncryptToBase64String(Guid key, byte[] input)
		{
			return Convert.ToBase64String(CDES.Encrypt(key, input));
		}

		public static string EncryptToBase64String(Guid key, string input)
		{
			return Convert.ToBase64String(CDES.Encrypt(key, input));
		}

		public static string EncryptToBase64String(string key, byte[] input)
		{
			return Convert.ToBase64String(CDES.Encrypt(key, input));
		}

		public static string EncryptToBase64String(string key, string input)
		{
			return Convert.ToBase64String(CDES.Encrypt(key, input));
		}

		public static string EncryptToBase64String(byte[] key, byte[] input)
		{
			return Convert.ToBase64String(CDES.Encrypt(key, input));
		}

		public static string EncryptToBase64String(byte[] key, string input)
		{
			return Convert.ToBase64String(CDES.Encrypt(key, input));
		}

		public static byte[] Decrypt(Guid key, byte[] input)
		{
			return CDES.Decrypt(key.ToByteArray(), input);
		}

		public static byte[] Decrypt(string key, byte[] input)
		{
			if (key == null)
				key = string.Empty;
			var bs = CDES.DefaultEncoding.GetBytes(key);
			bs = CMD5.MD5.ComputeHash(bs);
			return CDES.Decrypt(bs, input);
		}

		public static byte[] Decrypt(byte[] key, byte[] input)
		{
			if (key == null || key.Length == 0)
				return CDES.Encrypt(string.Empty, input);

			var des = System.Security.Cryptography.DES.Create();
			if (key.Length != 8)
				key = CMD5.MD5.ComputeHash(key);
			des.Key = new byte[] { key[0], key[2], key[4], key[6], key[8], key[10], key[12], key[14] };
			des.IV = new byte[] { key[1], key[3], key[5], key[7], key[9], key[11], key[13], key[15] };
			var msR = new System.IO.MemoryStream(input);
			var i = msR.ReadByte();
			var msW = new System.IO.MemoryStream();
			var cs = new System.Security.Cryptography.CryptoStream(msR, des.CreateDecryptor(), System.Security.Cryptography.CryptoStreamMode.Read);
			while (true)
			{
				i = cs.Read(input, 0, input.Length);
				if (i == 0)
					break;

				msW.Write(input, 0, i);
			}
			cs.Close();
			input = msW.ToArray();
			msR.Close();
			msW.Close();
			des.Clear();
			return input;
		}

		public static string DecryptFromBase64String(Guid key, string input)
		{
			return CDES.DefaultEncoding.GetString(CDES.Decrypt(key, Convert.FromBase64String(input)));
		}

		public static string DecryptFromBase64String(string key, string input)
		{
			return CDES.DefaultEncoding.GetString(CDES.Decrypt(key, Convert.FromBase64String(input)));
		}

		public static string DecryptFromBase64String(byte[] key, string input)
		{
			return CDES.DefaultEncoding.GetString(CDES.Decrypt(key, Convert.FromBase64String(input)));
		}
	}
}
